home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-13 | 97.8 KB | 2,328 lines |
- Shadow.library Documentation
- Library Version 5.0
-
- By David Navas
- Updated: 13 Nov 1992
-
- Copyright © 1992 by David Navas
- All Rights Reserved
-
- Method definition for the following classes as defined in SHADOW 5.0:
- DirectorClass
- MetaClass
- MetaCluster
- PatcherClass
- ProcessClass
- RootClass
- RootCluster
-
-
- What this document describes:
-
- This document is meant to be a reference appendix much in the same way
- that Appendix B in the RKM:Libraries 3rd edition (ISBN 0-201-56774-1)
- is for BOOPSI. If you have not read either Chapter 12 of the
- RKM:Libraries ("BOOPSI -- Object-Oriented Intuition"), or Appendix B
- ("BOOPSI Class Reference"), it is highly recommended that you peruse
- them. Although SHADOW's object-oriented implementation is slightly
- different than BOOPSI's, this reference attempts to mimic the RKM
- layout as much as is reasonably feasible, and much common ground can
- be found between the two.
-
- Where BOOPSI is intended to address the needs of Intuition, SHADOW
- attempts to address a more comprehensive superset of needs. As
- such, while programming SHADOW is rather simple, understanding it
- in its entirety can be intimidating.
-
- This document does not profess to be an exhaustive overview of SHADOW
- itself. Instead, its intent is to inform potential programmers of the
- nuances of each of the individual method calls within each of the
- available default classes.
-
-
- OVERVIEW and REVIEW:
-
- In SHADOW's version of the Object-Oriented Programming model, as with
- BOOPSI's version, everything is an OBJECT. In particular, under SHADOW,
- everything that deals with the Object-Oriented part of SHADOW begins
- with the structure CoreObject [include:shadow/core.h] which is defined
- as being a combination of the OBJECT's cob_class and its cob_useCount.
-
- The cob_useCount of an OBJECT is used for resource tracking. For the
- most part, in order to deal with this document, the cob_useCount is
- not required to be fully understood. A broader discussion of it is
- available elsewhere. All interaction with this field MUST proceed
- via the DropObject() and UseObject() calls and the CheckUseCount()
- macro.
-
- The cob_class field is defined to be the "blueprints" of an object.
- The object's ATTRIBUTEs (alternatively referred to as properties or
- instance variables in other Object-Oriented Programming Models) and the
- object's METHODs (alternatively referred to as functions in other
- programming models) are all described in the OBJECT's cob_class.
-
- [Special note:
- If an OBJECT's cob_class is NULL, the longword after the CoreObject
- is assumed to contain the size of the object so that the OBJECT
- can be freed when the cob_useCount drops to zero during a
- DropObject() call. NULL cob_class OBJECTs are useful to pass around
- when large amounts of data need to be passed from program to
- program -- and in particular, when they need to be passed in an
- asynchronous, resource-tracked manner. A zero is a legal size for
- the OBJECT (the longword after the CoreObject structure), and signals
- a program's wish for DropObject() NOT to free the OBJECT when the
- usecount falls to zero. see: 'struct ClasslessObject' in
- include:shadow/core.h]
-
-
- A cob_class is a special kind of OBJECT. It is guaranteed to contain
- a Meta structure [include:shadow/coreMeta.h], which is a structure that
- contains important method parsing and attribute parsing information,
- AS WELL AS all the information contained in the CoreObject structure.
-
-
- METAS:
-
- This leads us to one of the most confusing elements of SHADOW --
- if we label all cob_classes as "Classes", what is the cob_class of a
- Class?
-
- Imagine a row of identical apartments in an apartment complex. If
- we model these apartments under an object-oriented paradigm, the
- apartments are instances (or OBJECTs) of a particular apartment-class.
- The apartment-class serves as a blueprint for each of the apartments,
- and, indeed, it is compelling to refer to the apartment blueprints
- AS the class of the apartments.
-
- These blueprints, however, are also instances (or OBJECTs) of a
- blueprint-class. The blueprint-class is itself described in numerous
- architectural books. But architectural books are instances
- (or OBJECTs) of a book-class. This seemingly infinite series of
- statements must terminate somewhere, and in real life it usually
- terminates at some fuzzy boundary of understanding. For example, while
- most people would readily agree that an apartment must have a
- blueprint, they would also have a great deal of trouble adequately
- describing just what a blueprint contains.
-
- Unfortunately, computers are stupid and lack the ability to deal with
- this kind of "fuzzy understanding."
-
- Fortunately, the reality is that this type of recursion always
- terminates. A "book" is described in a "dictionary" and a "dictionary"
- is described in itself. In short, we end in a self-referencing
- recursion -- something is described by itself.
-
- Under SHADOW, the responsibility of parsing attribute requests and
- method requests for a Class (or any cob_class, for that matter) is
- the domain of a Meta. A Meta is the "something" in SHADOW which
- refers to itself. More concretely, SHADOW's Metas are OBJECTs
- whose cob_class points back to itself.
-
- A Meta contains the same type of information as a Class, excepting
- that the OBJECT's cob_class points back to itself. This self-referencing
- implies that all methods and attribute requests [ie: DoShadow(),
- FindAttribute(), etc.) for Metas are handled by the Meta itself. This
- also implies that a Meta is an instance of itself.
-
- However, paradoxically, the instances of Metas are classes; or, less
- ambiguously, the instances of Metas are OBJECTs which can legally
- reside in the cob_class field of other OBJECTs. This implies,
- correctly, that a Meta is just another kind of cob_class....
-
- Metas exist for one main reason: METH_CREATE -- or, rather, the
- flexibility in creating new Metas which define new ways of creating
- object instances. For instance, the ability to create Metas gives
- you, the programmer, the ability to create Classes that create
- their instance OBJECTs via a calloc() call, instead of an AllocMem()
- call.
-
- All OBJECTs are created by sending an OOP METH_CREATE "message" to the
- associated cob_class of the OBJECT you want created. Because all
- methods of all objects are really handled by the cob_class of the
- OBJECT, sending a "message" to a cob_class implies that the method
- request is really "handled" by the cob_class' Meta. Hence, the only
- way to change a program's "object creation" call is to "subclass" a
- Meta, creating a new Meta and rebinding the METH_CREATE method to
- your own code. [see: Figure.SLM.1]
-
- If this has confused you, you may want to refer back to Introduction.doc
- which also contains information about the distinctions between Metas,
- cob_classes, OBJECTs, etc. It is important to understand the nuances
- of Metas if you are to read this appendix in its entirety. If, instead,
- you are merely trying to reference a particular method in a class
- like PROCESS_CLASS, then Metas are not important to you.
-
-
- OF SELECTORS, METHODS, and OOP MESSAGES:
-
- The discussion two paragraphs above introduces the OOP term "message"
- into a programming model where "message" is already used to refer to
- passing data from task to task, or passing data across machines.
-
- As page 293 of the RKM:Libraries points out:
-
- "The term 'message' used in object oriented terminology can be [a]
- little confusing to the Amiga programmer because the Boopsi
- message has nothing to do with an Exec message."
-
- The usage is similarly confusing under SHADOW. Object-oriented
- terminology uses the word "message" as a means of selecting which
- method (or function) to execute to complete the method invocation
- request (DoShadow(), DoShadowAsync(), PreParseShadow(), etc.).
-
- From now on, the less ambiguous terms "selector", "method", and
- "invoke" will be used to describe the process of requesting and
- servicing OOP "messages". The term selector will refer to the OOP
- term "message". It is hoped that the terms "method" and "invoke" are
- similarly easily understood. We can, therefore, now say that a
- programmer requests a method (a function) by passing a selector
- (METH_CREATE, METH_PROC_ASSOCIATE, etc.) to the correct invoking macro
- or library function (CallSuper(), DoShadow(), DoShadowInProcess(),
- DSM(), etc.). These terms are, hopefully, less ambiguous.
-
-
- SELECTORS:
-
- Under SHADOW, selectors are implemented as pointers to strings. This
- allows for large, unambiguous name-spaces, and with a few
- straight-forward naming conventions, eliminates the need to surpervise
- the creation of third party selectors. SHADOW goes to a few lengths
- to ensure that these strings have as little overhead on method
- invocations as possible through the use of buffering method lookups,
- and an implementation of a "strings" table which allows each string
- that is used as a method-selector (or an attribute, class, etc.) to be
- given a unique 32bit address.
-
- Thus, if a selector is not found in the buffered lookup table (ie: the
- method wasn't recently invoked), the selector is found in the hashed
- array of system strings, and the 32bit returned value is used to
- radix search through the MethodTable of the cob_class.
-
-
- ATTRIBUTES:
-
- Attributes are also "named" using strings. Attributes contain the
- definition of the variables that are stored in an object. Each
- named attribute can refer to an entire C-structure of variables,
- allowing for the usual object-oriented separation of each subclass'
- attributes from its associated superclass'. However, it is entirely
- possible for a superclass to search for a subclass' set of variables
- (as attributes, like methods, are bound at run-time, so no compilation
- check can be done, and run-time checking would be prohibitive). Care
- on the part of the programmer must be taken that either superclasses
- don't know about their subclass' attributes, or aren't effected by
- their absence or existence. In other words, for code such as:
-
- SuperClassMethod(METHOD_ARGS, other_args)
- {
- struct MySubClassVars mscv = FindAttribute(object, ATTR_SUB_VARS);
-
- .
- .
- .
- }
-
- ...you must check "mscv" against NULL, and take the appropriate actions.
- In most cases, however, you should avoid such behaviour.
-
-
- CLUSTERS:
-
- In addition to Classes, and as an example of "subclassing" Metas,
- SHADOW defines Clusters as the cob_class of COMPOSITEs. A
- COMPOSITE is sort of like a bag of OBJECTs. When the COMPOSITE is
- fully initialized (see: METH_INIT), it contains a number of OBJECTs
- stored in a binary tree. The attribute of this binary tree is
- represented as ATTR_BAG. Therefore, you can get a pointer to the
- binary tree (which is what y0u need to pass to the various binary tree
- manipulation functions) by calling:
-
- AVLTree *bt;
-
- bt = (AVLTree *)FindAttribute(my_compositeObject, ATTR_BAG);
-
-
- Or you can merely use the structure 'struct CoreComposite' and
- de-reference directly off of that [include:shadow/coreRoot.h].
-
- Once the COMPOSITE is initialized, you may add or remove as many
- objects as you like to/from the ATTR_BAG binary tree. Caution: if you
- remove an object, please remember to send the removed object a
- METH_REMOVE method so that it can be removed from its cob_class'
- instance tree as well.
-
-
- INHERITENCE:
-
- Methods are inherited from an object's cob_class' superclass, as are
- attributes. Inheritence, subclassing, and superclasses are all terms
- that should be familiar to you either from previous object-oriented
- programming, or from your perusal of my Glossary.doc and the
- RKM:Libraries 3rd edition BOOPSI discussions. Like Appendix B
- in RKM:Libraries, this document describes each class in turn,
- describing the new methods, the modified methods, the new attributes,
- the superclass, and the include files that are associated with each
- separate class.
-
- Each class inherits methods and attributes from its superclass by
- default. Therefore we will talk about classes in the order in which
- they appear in the inheritence hierarchy. The hierarchy is as follows:
-
- MetaClass
- |
- |
- MetaCluster
-
-
-
-
-
- RootClass
- ________/ | \__________
- | | |
- DirectorClass PatcherClass ProcessClass
-
-
-
-
- RootCluster
-
-
- CLASS OVERVIEW:
-
- MetaClass and MetaCluster are the meta descriptions for Classes and
- Clusters. These are rarely used directly by the end programmer.
- They are used indirectly for such things as creating instances,
- classes, and subclasses of themselves.
-
- RootClass and RootCluster are the roots of the Class and Cluster
- inheritence hiearchies They do things like store the object into the
- class' ATTR_INSTANCETREE (a watched binary tree), and they define
- clusters as starting with an ATTR_BAG. Again, these are rarely
- directly used, they are more often used merely as classes to subclass.
-
- DirectorClass is the class for director objects, usually referred to as
- watchers. SHADOW defines a type of variable called WatchedVariables.
- Director objects are the objects responsible for actually watching
- these WatchedVariables. They provide Notification methods, and also
- support the ability to watch more than one variable at a time via the
- ESTABLISH/TERMINATE method protocol. Browser uses Director objects
- (or watchers) in three separate ways.
-
- Browser uses watchers to watch the instance tree of every opened
- Meta/Class/Instance listing so that it can keep the listings as current
- as possible. It also uses watchers to keep the "number of patches"
- in the Method display windows current. In addition, browser uses
- something known as a "class watcher" to watch all of the instances of
- all of the subclasses of a certain class -- in this case, it watches
- the ATTR_GUICHILDREN of all windows and gets notification every time
- a window has a child (usually a gadget) added or removed from the
- ATTR_GUICHILDREN tree.
-
-
- PatcherClass is the class for method patch objects. Every method in
- SHADOW can be patched -- this is SetFunction() done right! Method
- patches for a class are located in a watched list referred to as
- ATTR_PATCHEDVERBS. Patches have a priority (higher priority patches
- get invoked before lower priority patches -- regular methods are default
- priority zero), can dynamically prevent subsequent patches of lower
- priority from being invoked, and may only patch a single verb at a time,
- unlike watchers. Please Note!: it is impossible to patch the DESTROY
- method -- see RemoveAllPatches() for more details.
-
- Patches are useful when attempting to change the behaviour of some
- non-native application, some feature of some class you don't like,
- or for distributing bug fixes.
-
-
- ProcessClass (more accurately referred to as ThreadClass, because of
- the way AmigaDOS treats Tasks/Processes) is the class for process
- objects. They attach themselves to your task->tc_UserData field,
- SO DON'T MESS WITH THAT FIELD! Process objects keep track of IPC
- ports, the parent task pointer (0 if no parent), the message for use
- during synchronous communications, etc. Each program that intends
- to invoke methods, either actively via DoShadow() or DSM(), or
- passively via DropObject() or possibly even via callbacks in the
- FindAttribute() code, should generally call InitOOProgram().
-
- Unfortunately, this makes subclassing ProcessClass for your own
- program's process more or less pointless because InitOOProgram()
- associates a default process to your already running program.
- Fortunately, because METH_SUB is actually a callback method, it is safe
- to create a subclass of Process Class and then send that class a
- METH_CREATE followed by a METH_PROC_ASSOCIATE as documented later in
- this file. The attribute ATTR_SHADOWPROCESS -must- be located eight
- bytes from the start of the object, so please don't define your own
- private process-class unless it is a subclass of ProcessClass.
- The exact contents of ATTR_SHADOWPROCESS are subject to change, and in
- fact HAVE changed from version 4 to version 5!
-
- Processes have become generally more useful in version 5 because of
- the much cleaner startup conventions, and the plethora of new
- method invocation possibilities. ASLClass, for instance,
- -automatically- starts up a new process each time a new AslObject
- would block the main gui process.
-
-
- METHOD CALLING CONVENTIONS
-
- All methods are invoked by DSM() with at least four parameters. The
- first is a pointer to an IPCMessage structure. If this parameter is
- non-NULL, it means that the method was invoked with an asynchronous
- method, and the passed IPCMessage is the message which was sent to the
- task. The name of this parameter is 'msg'.
-
- The second parameter is the object that the method was invoked on.
- However, the term 'object' would be ambiguous, as the instance that
- the method was invoked on may well be a class-object or a meta-object.
- Nevertheless, in the code, the parameter is named 'object'. In other
- object-oriented languages, this is often defined to be 'self' or 'this'.
- If you prefer this notation, the definition of METHOD_ARGS can be found
- in include:shadow/misc.h. Feel free to change them for your own
- convenience.
-
- The third parameter is the class pointer, which is the pointer to
- the class for which the method is defined (under the hierarchy of the
- object->cob_class, of course). The parameter's name in the code is
- 'class'.
-
- The last default parameter is the selector itself. This is guaranteed
- to be a pointer to the system string which stores the name of the
- method. This parameter is named 'MethodID'.
-
- All four of these parameters can be found in the METHOD_ARGS #define in
- the include file: shadow/misc.h.
-
-
- SYSTEM CLASS REFERENCE
-
- Class: META_CLASS
- Superclass: -none-
- Include File: <shadow/coreMeta.h>
-
- This is the universal meta for all other metas.
-
- Attributes:
- ATTR_CORE -- The minimal class variables, including the
- attribute and method table pointers.
- Implemented as struct Meta and typedef'd
- as META.
- Access to this attribute is priviledged,
- and usually unnecessary anyway.
-
- ATTR_PATCHEDVERBS -- Watched list of method patches.
- Access to this attribute is managed through
- the method patching class.
-
- ATTR_INSTANCETREE -- Watched binary tree of meta's instances.
- Metas are kept on a special watched binary
- tree located in ShadowBase->sb_metaTree.
- Classes (as instances of MetaClass) are
- kept on this INSTANCETREE. Note that even
- though Metas are, strictly, instances of
- themselves, they do not exist on their
- own INSTANCETREE.
- The Class Browser uses the watched aspect
- of this binary tree and gets notification
- whenever any new Class is created and
- added to this tree. Instances are added
- to the tree when the METH_INIT is sent to
- them.
-
- New Methods:
-
- METH_CREATE
- run as:
- function in invoker's process.
-
- arguments:
- none.
-
- NOTE: this function may NOT be invoked asynchronously!
- Returns a pointer to an uninitialized object. Sets an
- error in the current process error field if it can't
- allocate an object-class "CANNOT_ALLOCATE_OBJECT"
- [see include:shadow/misc.h]
-
- purpose:
- CreateInstance() uses this method to create a new instance
- of a class. Programs which prefer to invoke the method
- directly can as well, however there is no known
- reason why programs would wish to do so, except,
- perhaps, for testing purposes.
-
- restrictions:
- none
-
- function:
- Allocates an instance of a particular class. IE:this is a
- method which is sent to a Class, not its instances.
- It creates an object, fills in the class field and any
- default attribute values as specified in the class attribute
- table, and returns the allocated object.
-
- Note that this object CANNOT have anything done to it UNTIL
- it is sent a METH_INIT. Among other things, the useCount is
- zero. DSM() correctly fails and frees the object if invoking
- the METH_INIT fails for any reason (like the destination
- process has it's port closed, or memory is running low).
-
- Memory is allocated :: (MEMF_PUBLIC | MEMF_CLEAR)
-
- example:
- .
- .
- .
- /*
- * Allocation example code.
- */
- procClass = FindShadowClass(PROCESS_CLASS);
- procObject = DoShadow(procClass,
- NULL,
- METH_CREATE,
- METHOD_END);
- procObject = DoShadow(procObject,
- NULL,
- METH_INIT,
- METHOD_END);
- DropObject(procClass);
- .
- .
- .
- /*
- * Cleanup code.
- */
- RemovObject(procObject);
-
-
- METH_DESTROY
- run as:
- function in invoker's process.
-
- arguments:
- none
-
- purpose:
- METH_DESTROY frees an object.
- When DropObject() notices that the usecount has fallen to
- zero, it invokes the METH_DESTROY method on the object.
-
- restrictions:
- You should never invoke this method yourself!
- This method is always invoked by DropObject()!
-
- function:
- Invalidates the cache for any cache lines with the class
- being destroyed. See InvalidateCache() for details.
- Frees any leftover watchers on the class
- [FreeObjectWatchers()], destroys the method and attribute
- tables, drops the class name and superclass references,
- frees the object, drops its class, and handles the case of
- transferring the pointer from the 'msg' field to
- non-existence, just in case this method is invoked
- asynchronously (which should NEVER happen). This is the
- second half of the two-level resource tracking. This
- function is invoked by DropObject() when the useCount of
- the object drops to zero, implying no one has a pointer to
- the object. As evidenced by the FreeObjectWatchers() call,
- this may not be entirely TRUE, but watchers are a special
- case.
- Also calls RemoveAllPatches().
-
- example:
- /*
- * Assuming the assert works, the DropObject()
- * invokes the METH_DESTROY method.
- */
- assert(CheckUseCount(object) == 1);
- DropObject(object); /*
- * This calls the METH_DESTROY method.
- * This is the only legal way to have
- * the METH_DESTROY method called.
- */
- /*
- * NOTE!!!! In practice, you do not assert() usecounts
- * like this anymore than you would assert any other kind
- * of usecount. In real life, the DropObject() calls
- * the object's METH_DESTROY method whenever the usecount
- * falls to zero. If the usecount is one before entering
- * DropObject(), then the usecount obviously falls to
- * zero, and the METH_DESTROY is then called. The assert
- * is there only to differentiate the many calls you can
- * make to DropObject() that do NOT invoke the
- * METH_DESTROY method from this case, which does.
- */
-
-
- METH_INIT
- run as:
- function in invoker's process.
- arguments:
- JSTR -- name of the class to create
- JOBJ -- optional superclass of the class to create.
- TAGL -- NULL terminated array of struct AttributeTag. NULL
- is also valid.
- TAGL -- NULL terminated array of struct MethodTag. NULL is
- also valid.
-
- Returns a pointer to the initialized object. NULL on
- failure. Object destroyed on failure....
-
- purpose:
- Initializes the class or meta by filling in the superclass,
- methods, and attributes of the new class or meta.
- Call this method directly ONLY when you are creating
- your own root of a "class" or meta hierarchy. Otherwise,
- the METH_SUB is far more useful.
-
- restrictions:
- Call this directly only for "root"s of cob_class
- hierarchies.
-
- function:
- Methods that are defined in metas have a rather disturbing
- property. Recall that metas are responsible for handling
- their own methods AS WELL AS the methods of their
- instances.
-
- However, the normal path of execution for a METH_INIT is to
- initialize all variables of the object being defined. As
- noted in the "purpose" field above, this includes the
- method and attribute arrays of the class/meta being
- defined. It is clearly impossible, therefore, for a meta
- to completely handle its own METH_INIT. What gives?
-
- Well, creation of "root" metas (that constitutes the
- META_CLASS -- META_CLUSTER is a subclass of META_CLASS)
- requires a call to the library function CreateMeta().
- CreateMeta() actually fills in the meta's method and
- attribute fields, and then invokes the METH_INIT on the
- (half-filled) meta.
-
- Therefore, it is up to this method call to distinguish
- the distinction between half-filled metas, and completely
- empty classes. This is accomplished by comparing
- object->cob_class to object. Recall that ALL metas are
- self-referencing by nature -- self-referencing in that
- the object->cob_class field points back to object. So,
- the METH_INIT distinguishes between the cases and takes
- the appropriate actions as listed below:
-
- If the method is being invoked on a meta,
- the superclass, attribute array, instance size, and
- method array are left alone.
- Otherwise, if the method is being invoked on a class
- that is not a meta, this function fills in the
- superclass, the attribute table, the instance size,
- and the method table.
-
- In either case, it fills in the class name, binds all the
- appropriate class watchers for its attributes [Ed:
- watched variables have both a list of watchers, and a
- pointer to a second list of watcher. SHADOW uses this
- second pointer to point to a list of watchers managed by
- the class. Under MetaClass and MetaCluster, these 'class'
- watchers are copied into all subclasses. See
- BindSuperWatchers() for more details], and adds the object
- into its class' ATTR_INSTANCETREE. In the case of a meta,
- this would be Shadow->sb_metaTree. It also calls
- BindWatchers() on the object which binds the second
- watch-list pointer of all watched variables to the class'
- attributes' SList. See the struct Attribute definition and
- the AutoDocs for BindWatchers().
-
- example:
-
- /*
- * Retrieve the meta in which to create the base class.
- */
- metaclass = FindWatchedTreeStringNode(
- &ShadowBase->sb_metaTree,
- META_CLASS);
- /*
- * Create the base class.
- *
- * myRootClustAttributes is a NULL terminated array
- * of AttributeTag structures.
- * myRootClustMethods is a NULL terminated array of
- * MethodTag structures.
- */
- myroot = CreateInstance(metaclass, NULL,
- NULL,
- MY_ROOT_CLASS,
- NULL,
- myRootClassAttributes,
- myRootClassMethods,
- METHOD_END);
- DropObject(metaclass); /*
- * Don't need the metaclass
- * pointer anymore.
- */
- .
- .
- .
-
- /*
- * Cleanup!
- */
- RemoveObject(myroot);
- .
- .
- .
-
- /*
- * Creation of MetaClass:
- */
- struct InitMeta __far globalIM = {
- NULL,
- NULL,
- NULL, /* METH_INIT is default */
- META_CLASS, /* meta name */
- NULL, /* no super. */
- metaClassAttrs,
- metaClassMethods,
- METHOD_END,
- };
- metaclass = CreateMeta(&globalIM);
- .
- .
- .
-
- /*
- * Cleanup!
- */
- RemoveObject(metaclass); /* this meta
- * no longer needed.
- */
-
-
- METH_REMOVE
- run as:
- function in invoker's process.
- arguments:
- none
-
- purpose:
- Removes a class from the system list, initiates the first
- pass of the two-level resource tracking algorithm.
- Call this method when you are done with a class and want
- it to be removed from being referenced by the system. The
- class will continue to exist until all references to it are
- gone -- that implies that all instances of the class are
- gone as each instance of a class is pointed to by the
- instance's cob_class field.
-
- RemoveObject() calls the METH_REMOVE function to Remove
- classes and objects.
-
- restrictions:
- After calling this method, you may not have circular
- references to this item, nor may you cause such
- circular references to come into existence.
-
- function:
- Frees all class watchers associated with this class. See
- FreeClassWatchers() for further details. Removes the
- instance (in this method, the instance is a Class) from its
- class' ATTR_INSTANCETREE. If this is a Meta being removed,
- the Meta is removed from ShadowBase->sb_metaTree instead.
- This is the first of the two-level resource tracking done
- on objects. In addition, removal from this tree implies
- that the system can no longer find your class/meta,
- effectively removing it from the system. It is not
- destroyed, however, until no one has a pointer to it
- (assuming they have used UseObject() and DropObject()
- appropriately. All self-references, either direct or
- indirect, should be eliminated in this method.
-
- example:
- /*
- * Cleanup code.
- */
- RemoveObject(FindShadowClass(MYDOS_CLASS));
- /*
- * FindShadowClass() returns a used class
- * pointer to MYDOS_CLASS.
- * RemoveObject() then invokes the METH_REMOVE
- * method, and DropObject()s the passed class.
- */
-
- .
- .
- .
-
- /*
- * More example Cleanup Code.
- * Assumes DosClass is already a valid pointer to your
- * class.
- */
- RemoveObject(DosClass);
- /*
- * RemoveObject() invokes the METH_REMOVE on
- * DosClass and DropObject()s the passed
- * class.
- * DosClass is no longer a valid pointer
- * to the DosClass object anymore. Indeed,
- * the DosClass itself may very well have
- * disappeared.
- */
- .
- .
- .
-
-
- METH_SUB
- run as:
- function in invoker's process.
- arguments:
- JSTR -- name of the class to create
- JOBJ -- optional superclass of the class to create. This
- method is, however, sent to the class that is to
- be subclassed, so if this parameter is NULL, it
- defaults to the object which the method was sent to.
- TAGL -- NULL terminated array of struct AttributeTag. NULL
- is also valid.
- TAGL -- NULL terminated array of struct MethodTag. NULL is
- also valid.
-
- purpose:
- Creates a new subclass.
- CreateSubClass() calls this method.
- You should probably use CreateSubClass(), but it takes
- parameters exactly equivalent to what's shown here, so
- it's good to reference this method when you need to
- know the arguments to pass to CreateSubClass().
-
- This is basically equivalent to a METH_CREATE followed
- by a METH_INIT where the object you invoke the
- METH_SUB on ends up being the superclass sent into the
- METH_INIT.
-
- restrictions:
- none
-
- function:
- Note the description of the complications of sending
- METH_INITs to metas in the METH_INIT description
- above. Note that the METH_SUB is really just a
- convenient wrapper around the METH_CREATE and the
- METH_INIT methods.
-
- If this method is invoked on a meta (that is, if object ==
- object->cob_class), then instead of invoking METH_CREATE
- and METH_INIT, this function MUST call CreateMeta() in
- order to setup the methds, attributes, etc. of the meta.
- In this case, the CreateMeta() is called with the InitMeta
- structure set as the parameter list passed into METH_SUB
- (minus the 'msg' pointer). CreateMeta() then calls the
- METH_INIT method as described in the CreateMeta() autodoc.
- The return value is equivalent to whatever CreateMeta
- returns.
-
- Otherwise, if the method isn't invoked on a meta, this
- method instantiates a meta (creating a Class Object)
- and sends a METH_INIT to it, returning whatever the INIT
- method returns.
-
- examples:
- /*
- * Creates a new class as a subclass of rootclass.
- */
- newClass = CreateSubClass(NULL, ROOT_CLASS,
- META_CLASS,
- MYDOS_CLASS,
- NULL,
- my_new_attributes,
- my_new_methods,
- METHOD_END);
-
- /*
- * Creates a new class as a subclass of some private class.
- */
- newClass2 = CreateSubClass(oldClass, NULL,
- NULL,
- MY_NEW_CLASS,
- NULL,
- my_new_attributes,
- my_new_methods,
- METHOD_END);
-
- /*
- * Creates a new meta as a "sub-meta" of metaclass.
- */
- newMeta = CreateSubClass(NULL, META_CLASS,
- NULL,
- MY_META,
- NULL,
- my_new_attributes,
- my_new_methods,
- METHOD_END);
-
- /*
- * Note: CreateSubClass is a stub routine that calls
- * METH_SUB.
- *
- * Note2: Don't forget to cleanup your allocations!
- */
-
- METH_SUPER
- run as:
- function in invoker's process.
- arguments:
- JSTR -- name of the class to create
- JOBJ -- optional subclass of the class to override. This
- method is, however, sent to the class that is to
- be "superClassed", so if this parameter is NULL, it
- defaults to the object which the method was sent to.
- TAGL -- NULL terminated array of struct AttributeTag. NULL
- is also valid.
- TAGL -- NULL terminated array of struct MethodTag. NULL is
- also valid.
-
- purpose:
- Creates a new superclass for an existing class.
- Thus, in effect, adding methods to an existing class tree.
-
- restrictions:
- The new superClass must be created as a subclass of the
- passed class' superclass [that is, the superclass of the
- object (class) the method was invoked on].
- The class must HAVE a superClass -- ie: you cannot
- invoke this method on ROOT_* classes.
- This new class may NOT add any new attributes.
-
- function:
- The METH_SUB method is invoked on the passed class'
- superclass. The InsertSuperClass() function is
- then called (this function flushes the method cache as
- well!).
-
- examples:
- /*
- * Creates a new superclass of a subclass.
- * Adds the methods specific in the my_new_method structure.
- */
- procClass = FindShadowClass(PROCESS_CLASS, META_CLASS);
- newClass = DoShadow(procClass, NULL, METH_SUPER,
- MY_INTERMEDIATE_CLASS,
- NULL,
- my_new_attributes,
- my_new_methods,
- METHOD_END);
- DropObject(procClass);
-
- .
- .
- .
-
- RemoveObject(newClass);
-
-
-
- Class: META_CLUSTER
- Superclass: META_CLASS
- Include File: <shadow/coreMeta.h>
-
- This is an example of a "submeta". It is really only intended
- for demonstration purposes. If you find a use for it yourself,
- so much the better!
-
- MetaCluster is the blueprints for a class that creates a placeholder
- for any number of other objects, and then creates those other
- objects as well. For example, you can create a workbench-icon
- cluster which describes a workbench icon as a collection of a file
- object and a graphic object. When the cluster is instantiated
- (creating a composite-object), the composite-object would have, as one
- of its attributes, a binary tree with the newly instantiated file and
- graphic objects in it.
-
- Attributes:
- ATTR_CLASSTABLE -- struct ClusterClassTable
- [see: include:shadow/coremeta.h].
- An array of classes that describes
- what objects the cluster should instantiate
- to put in the composite-object's binary tree.
-
- Modified Methods:
- METH_DESTROY
- run as:
- function in invoker's process.
-
- arguments:
- none
-
- purpose:
- METH_DESTROY frees an object.
- When DropObject() notices that the usecount has fallen to
- zero, it invokes the METH_DESTROY method on the object.
-
- restrictions:
- You should never invoke this method yourself!
- This method is always invoked by DropObject()!
-
- function:
- ATTR_CLASSTABLE is freed.
- Method is then routed to the superclass.
-
- example:
- See example under META_CLASS
-
-
- METH_INIT
- run as:
- function in invoker's process.
-
- arguments:
- JSTR -- name of the class to create
- JOBJ -- optional superclass of the class to create.
- TAGL -- NULL terminated array of struct AttributeTag. NULL
- is also valid.
- TAGL -- NULL terminated array of struct MethodTag. NULL is
- also valid.
- TAGL -- NULL terminated array of classes to fill in the
- ATTR_CLASSTABLE. NULL is also valid.
-
- Returns a pointer to the initialized object. NULL on
- failure. Object destroyed on failure....
-
- purpose:
- Initializes the class or meta by filling in the superclass,
- methods, and attributes of the new class or meta.
- Call this method directly ONLY when you are creating
- your own root of a "class" or meta hierarchy. Otherwise,
- the METH_SUB is far more useful.
-
- restrictions:
- Call this directly only for "root"s of cob_class
- hierarchies.
-
- function:
- Please refer to the note about meta creation in the
- METH_INIT method function description of META_CLASS.
-
- This method creates the array for the ATTR_CLASSTABLE
- attribute.
- The method is then routed to the superclass.
-
- example:
-
- /*
- * Retrieve the meta in which to create the base class.
- */
- metacluster = FindWatchedTreeStringNode(
- &ShadowBase->sb_metaTree,
- META_CLUSTER);
- /*
- * Create the base cluster.
- *
- * myRootClustAttributes is a NULL terminated array
- * of AttributeTag structures.
- * myRootClustMethods is a NULL terminated array of
- * MethodTag structures.
- * myRootClustClasses is a NULL terminated array of
- * class -pointers-.
- */
-
- myroot = CreateInstance(metacluster, NULL,
- NULL,
- MY_ROOT_CLUSTER,
- NULL,
- myRootClustAttributes,
- myRootClustMethods,
- myRootClustClasses,
- METHOD_END);
- DropObject(metacluster); /*
- * Don't need the metaclass
- * pointer anymore.
- */
- .
- .
- .
-
- /*
- * Cleanup!
- */
- RemoveObject(myroot);
- .
- .
- .
-
-
- METH_SUB
- run as:
- function in invoker's process.
-
- arguments:
- JSTR -- name of the class to create
- JOBJ -- optional superclass of the class to create. This
- method is, however, sent to the class that is to
- be subclassed, so if this parameter is NULL, it
- defaults to the object which the method was sent to.
- TAGL -- NULL terminated array of struct AttributeTag. NULL
- is also valid
- TAGL -- NULL terminated array of struct MethodTag. NULL is
- also valid.
- TAGL -- NULL terminated array of classes to fill in
- ATTR_CLASSTABLE with. NULL is also valid.
-
- purpose:
- Creates a new subclass.
- Adds an additional class_array parameter which is forwarded
- to the METH_INIT method.
- See the desription of the METH_SUB method purpose in
- META_CLASS description above.
-
- restrictions:
- none
-
- function:
- Functionally identical to the METH_SUB in META_CLASS except
- that this method forwards the class_array parameter to
- the METH_INIT of META_CLUSTER.
-
- example:
- /*
- * Creates a brand new meta for clusters.
- */
- metaclass = FindWatchedTreeStringNode(
- &ShadowBase->sb_metaTree,
- META_CLASS);
- metaCluster = DoShadow(metaclass,
- NULL,
- METH_SUB,
- META_CLUSTER,
- metaclass,
- metaClusterAttrs,
- metaClusterMethods,
- METHOD_END);
- DropObject(metaclass); /*
- * Uninterested in this pointer
- * now.
- */
-
- /*
- * Creates a new class as a subclass of rootcluster.
- */
- newCluster = CreateSubClass(NULL, ROOT_CLUSTER,
- META_CLUSTER,
- MY_CLUSTER,
- NULL,
- my_new_attributes,
- my_new_methods,
- my_new_classes,
- METHOD_END);
-
-
- Class: ROOT_CLASS
- Superclass: -none-
- Include File: <shadow/coreRoot.h>
-
- This is the root cob_class for all META_CLASS classes.
-
- Attributes:
- none
-
- Methods:
- METH_DESTROY
- run as:
- function in invoker's process.
-
- arguments:
- none
-
- purpose:
- METH_DESTROY frees an object.
- When DropObject() notices that the usecount has fallen to
- zero, it invokes the METH_DESTROY method on the object.
-
- restrictions:
- You should never invoke this method yourself!
- This method is always invoked by DropObject()!
-
- function:
- Frees any leftover watchers on the object
- [FreeObjectWatchers()], frees the object, and drops its
- class. Handles the case of transferring the pointer from
- the 'msg' field to non-existence, just in case this method
- is invoked asynchronously (which should NEVER happen).
- This is the second half of the two-level resource tracking.
- This function is invoked by DropObject() when the usecount
- of the object drops to zero, implying no one has a pointer
- to the object. As evidenced by the FreeObjectWatchers()
- call, this may not be entirely TRUE, but watchers are a
- special case.
-
- example:
- See example under META_CLASS
-
-
- METH_INIT
- run as:
- function in invoker's process
-
- arguments:
- JSTR -- name of the object to create (optional). If
- specified, object stored on ATTR_INSTANCETREE is
- sorted by the address of the string, rather than
- the address of the object itself.
-
- Returns a pointer to the initialized object. NULL on
- failure.
-
- purpose:
- Initializes the object and makes it a part of the
- system-shared resources.
- In reality, ROOT_CLASS exists to be subclassed.
-
- restrictions:
- none
-
- function:
- Adds object to ATTR_INSTANCETREE of its class, either sorted
- by the address of the passed string, or, if NULL string, by
- the object's own address. Note that these are AVL trees,
- so the tree remains well-balanced, regardless of the ordering
- of allocated memory.
-
- Also calls BindWatchers() to bind all the watched attributes
- of the object's second List to the class attribute's watched
- list. See BindWatchers() for more details.
-
- example:
- /*
- * Create an instance of ROOT_CLASS
- */
- rootObject = CreateInstance(NULL, ROOT_CLASS,
- META_CLASS,
- MY_OBJECT_NAME,
- METHOD_END);
- .
- .
- .
-
- /*
- * Cleanup!
- * NOTE!!! You must call the METH_REMOVE directly
- * with the name of the object or the removal will
- * not occur correctly (ie: not at all).
- */
- DoShadow(rootObject, NULL, METH_REMOVE, MY_OBJECT_NAME,
- METHOD_END);
-
- /*
- * Note2: usually you keep the object name in the object's
- * instance as handled by some superclass. It is highly
- * suggested that you put such names into the FIRST
- * attribute as the FIRST field for future compatibility
- * reasons.
- */
- DropObject(rootObject);
-
-
- METH_REMOVE
- run as:
- function in invoker's process.
-
- arguments:
- JSTR -- optional string under which the object might have
- been stored (in the ATTR_INSTANCETREE). Iif the
- METH_INIT was invoked with a string as a
- parameter, then the METH_REMOVE better be, or it
- will fail to work properly.
-
- purpose:
- Removes an object from the class' ATTR_INSTANCETREE.
- Initiates the first pass of the two-level resource tracking
- algorithm. Call this method when you are done with an
- object and want it to be removed from being referenced by
- the system. The object will continue to exist until all
- references to it are gone.
-
- RemoveObject() calls the METH_REMOVE function to Remove
- classes and objects.
-
- restrictions:
- If you called the METH_INIT on this object with a non-NULL
- name-parameter, you MUST call the METH_REMOVE with this
- same name!
-
- After calling this method, you may not have circular
- references to this item, nor may you cause such
- circular references to come into existence.
-
- function:
- Removes the object from its class' ATTR_INSTANCETREE.
-
- example:
- see the METH_INIT method example for this class above.
-
-
- Class: ROOT_CLUSTER
- Superclass: -none-
- Include File: <shadow/coreRoot.h>
-
- This is the root cob_class for all META_CLUSTER clusters.
-
- Attributes:
- ATTR_BAG -- binary tree which all objects are stored on.
- NOT a watched binary tree!
-
- Modified Methods:
- METH_DESTROY
- run as:
- function in invoker's process.
-
- arguments:
- none
-
- purpose:
- METH_DESTROY frees an object.
- When DropObject() notices that the usecount has fallen to
- zero, it invokes the METH_DESTROY method on the object.
-
- restrictions:
- You should never invoke this method yourself!
- This method is always invoked by DropObject()!
-
- function:
- Removes all objects on the composite's ATTR_BAG and sends
- a METH_REMOVE to all of them.
- Method is then routed to the superclass.
-
- example:
- See example under META_CLASS
-
-
- METH_INIT
- run as:
- function in invoker's process
-
- arguments:
- JSTR -- name of the object to create (optional). If
- specified, object stored on ATTR_INSTANCETREE is
- sorted by the address of the string, rather than
- the address of the object itself.
-
- Returns a pointer to the initialized object. NULL on
- failure.
-
- purpose:
- Initializes the object and makes it a part of the
- system-shared resources.
- In reality, ROOT_CLUSTER exists to be subclassed.
-
- restrictions:
- none
-
- function:
- METH_CREATEs and METH_INITs (without arguments) all
- objects whose classes are on the ATTR_CLASSTABLE of this
- composite's cluster. Objects are stored on the ATTR_BAG's
- binary tree under the name of the class.
-
- Method continues in exactly the way that the METH_INIT
- method does in the ROOT_CLASS as described above.
-
- example:
- /*
- * Create an instance of ROOT_CLUSTER
- */
- rootObject = CreateInstance(NULL, ROOT_CLUSTER,
- META_CLUSTER,
- MY_OBJECT_NAME,
- METHOD_END);
- .
- .
- .
-
- /*
- * Cleanup!
- * NOTE!!! See notices in the METH_INIT example oF
- * ROOT_CLASS above.
- */
- DoShadow(rootObject, NULL, METH_REMOVE, MY_OBJECT_NAME,
- METHOD_END);
- DropObject(rootObject);
-
-
- METH_REMOVE
- run as:
- function in invoker's process.
-
- arguments:
- JSTR -- optional string under which the object might have
- been stored (in the ATTR_INSTANCETREE). If the
- METH_INIT was invoked with a string as a
- parameter, then the METH_REMOVE better be, or it
- will fail to work properly.
-
- purpose:
- Removes a composite from the cluster's ATTR_INSTANCETREE.
- Initiates the first pass of the two-level resource tracking
- algorithm. Call this method when you are done with a
- composite and want it to be removed from being referenced by
- the system. The composite will comtinue to exist until all
- references to it are gone.
-
- RemoveObject() calls the METH_REMOVE function to Remove
- all classes and objects.
-
- restrictions:
- If you called the METH_INIT on this composite with a
- non-NULL name-parameter, you MUST call the METH_REMOVE with
- this same name!
-
- After calling this method, you may not have circular
- references to this item, nor may you cause such
- circular references to come into existence.
-
- function:
- Removes the composite from its clster's ATTR_INSTANCETREE.
-
- example:
- see the METH_INIT method example for this cluster above.
-
-
- Class: DIRECTOR_CLASS
- Superclass: ROOT_CLASS
- Include File: <shadow/watcher.h>
-
- The class that creates watchers to establish notification of changes
- to watched variables.
-
- Attributes:
- ATTR_MANAGER -- struct ManagementNode
- [see: include:shadow/watcher.h].
- The place where useful information about the
- director is stored. For instance, information
- managing the conditions under which
- notification is sent, and to whom
- it is sent.
- ATTR_DIRECTOR -- a WatchedList. It is a list of all the
- established connections that have been made;
- in short, a list of all objects this Director
- is watching. Interestingly, you can get
- notification of when the notification lists
- change. And, of course, you can even have a
- class watcher watch everything at once!
-
- New Methods:
- METH_DIRECTOR_ESTABLISH
- run as:
- function in invoker's process.
-
- arguments:
- APTR -- the attribute-name of the object to watch, or a
- pointer to the actual watchedVariable, if no
- object is specified. This implies that this
- method CANNOT be safely invoked ASYNCronously.
- JOBJ -- the object in which the WatchedVariable is. If
- this parameter is NULL, the method assumes that
- the APTR is a pointer to the WatchedVariable, and
- not the name of the attribute.
- long -- priority of the watcher.
-
- Returns a handle to the connection. You should either
- DropObject() the handle, or keep it to pass to the
- TERMINATE method, after which you should DropObject() it....
-
- purpose:
- Use this watcher to watch a particular watched variable.
- You should be prepared to service notifications of
- changes prior to invoking this method.
- All connections through a single "watcher" (or "director-
- object") will have notification sent to the ONE destination
- that that watcher had set up for it in its METH_INIT code.
-
- restrictions:
- May not be called asynchronously by DSM(). By default,
- this method is never run asynchronously.
-
- function:
- Establishes a connection and adds that connection to the
- ATTR_DIRECTOR list of connections. Uses either
- AddClassWatcher() or AddWatcherNode(), depending on the
- type of Watcher this director-object is. Please see the
- AutoDocs for more information on these functions.
-
- The Watcher may either be a SHADOW_OBJECT watcher or a
- SHADOW_CLASS watcher. This is specified in the flags
- argument to the METH_INIT.
-
- examples:
- /*
- * Create a director object.
- * This is an example of a class watcher.
- */
- GlobalDirector = CreateInstance(NULL,
- DIRECTOR_CLASS,
- META_CLASS,
- "WatchWindows",
- object,
- METH_DIRECTOR_NOTIFY,
- (W_INSERT_NODE | W_REMOVE) |
- (SHADOW_CLASS << 16) |
- W_FLAG_AUTOBREAK |
- W_FLAG_AUTOREMOVE,
- METHOD_END);
-
- /*
- * Establish the actual connection. We don't care if
- * GlobalDirector wasn't created successfully (ie: it is
- * NULL), so that makes things easier.
- *
- * We are watching all the ATTR_GUICHILDREN of every instance
- * whose class is a subclass of WINDOW_CLASS
- */
- windowClass = FindShadowClass(WINDOW_CLASS);
- DropObject(DoShadow(GlobalDirector,
- NULL,
- METH_DIRECTOR_ESTABLISH,
- ATTR_GUICHILDREN,
- windowClass,
- METHOD_END));
- DropObject(windowClass);
-
- .
- .
- .
- /*
- * Cleanup!
- *
- * Note, because we INIT'd the director with the AUTO_BREAK,
- * the director's connections are terminated when the
- * METH_REMOVE is sent.
- *
- * Because we dropped the actual handle that the
- * ESTABLISH method returned, this is the only way we
- * can terminate the connection!
- */
- RemoveObject(GlobalDirector);
-
- ----------
-
- /*
- * This is an example of an object watcher.
- */
- /*
- * Create the director to watch the children of this object.
- *
- * When this object's children reaches zero, this object
- * should GO AWAY!
- */
-
- director = CreateInstance(NULL,
- DIRECTOR_CLASS,
- META_CLASS,
- "WatchBlockedChildren",
- object,
- METH_DIRECTOR_NOTIFY,
- (W_INSERT_NODE | W_REMOVE) |
- (SHADOW_OBJECT << 16) |
- W_FLAG_AUTOBREAK |
- W_FLAG_AUTOREMOVE,
- METHOD_END);
- /*
- * Establish the conection for the director.
- */
- handle = DoShadow(director,
- NULL,
- METH_DIRECTOR_ESTABLISH,
- ATTR_GUICHILDREN,
- object, /* object being watched */
- METHOD_END))
-
- .
- .
- .
-
- /*
- * Cleanup!
- */
- DoShadow(director, NULL, METH_DIRECTOR_TERMINATE, handle,
- METHOD_END);
-
- /*
- * Note: because this director was METH_INIT'd as
- * W_FLAG_AUTOREMOVE, there is no reason to call
- * RemoveObject() on the director as the METH_REMOVE
- * has already been sent. Recall, however, that
- * RemoveObject() both sends the METH_REMOVE and
- * drops the object from further use. DropObject(),
- * therefore, still needs to be called....
- */
- DropObject(director);
-
- METH_DIRECTOR_TERMINATE
- run as:
- function in invoker's process.
-
- arguments:
- JOBJ -- either the handle as returned by the ESTABLISH
- method, or a pointer to the object from which a
- watcher should be removed. The latter case
- should be restricted to the
- Free[Object|Class]Watchers() functions. Mostly
- because you are not guaranteed which handle of
- the watcher is removed. For instance, if one
- watcher is watching more than one watched
- variable of a single object, then invoking
- TERMINATE with the object being watched may
- release the watcher from any of those watched
- variables.
- long -- flags dictating whether this is a handle, or
- the object being watched, not specifying
- this parameter defaults to the type 'handle'
- (0), the other case is W_SORT -- value 1.
- purpose:
- Terminates a connection.
- Is used by the system to terminate all connections.
-
- restrictions:
- You should always pass the handle that you received from
- the ESTABLISH method as the JOBJ and not pass any
- second argument (defaults to zero).
- You may not run this method asynchronously to the caller.
-
- function:
- If flags are NULL, then simply removes the connection
- that that handle symbolizes. If this is the last
- connection, and if the AUTOREMOVE flag was specified in
- the INIT method, then the Director is Remove()'d from the
- system.
-
- Otherwise, if SHADOW_SORT is specified, the first handle
- on the list that is stored as being authorized by the
- passed object is terminated.
-
- Uses RemoveClassWatcher() or RemoveWatcherNode()
- internally to remove the watcher from the watching-list.
- Please see the AutoDocs for more information on these
- functions.
-
- example:
- see the METH_DIRECTOR_ESTABLISH method example for this
- class above.
-
-
- METH_DIRECTOR_NOTIFY
- run as:
- function in invoker's process.
-
- arguments:
- long -- Flags specifying what changed.
- APTR -- A pointer to the WatchedVariable that caused the
- notification. Note: this pointer will NOT be
- valid if sent ASYNC! This implies that the method
- to which notification is sent might also inherit
- nonsense in this value, so don't do anything
- brash with the NOTIFY method!
- APTR -- The new node/value of the WatchedVariable. Once
- again, ASYNC causes nightmares.
- JSTR -- The name of the new node, if specified.
-
- purpose:
- A change occurred someplace that this watcher was watching.
- The system calls this function with the correct flags and
- arguments, depending on the type of change that occurred.
-
- restrictions:
- You may not run this method asynchronously to the caller.
- You should not have to call this method directly. Instead,
- use the library function call, WatcherDispatch().
-
- function:
- If this Director is interested in the particular piece of
- information being broadcast, then notification is sent out.
-
- The following are the flags that effect this control.
- These are the flags in the lower 16bits of the flags field
- sent to the INIT function.
-
- /*
- * Match either.
- */
- #define W_CHANGE_ZERO 1
- #define W_CHANGE_NON_ZERO 2
- #define W_CHANGE_VALUE 3
-
- /*
- * Match exactly
- */
- #define W_NODE 4
- #define W_WATCH_CHANGE 8
- #define W_REMOVE 16
- #define W_INSERT 32
-
- /*
- * Control matching.
- */
- #define W_MATCH 64
- #define W_MATCH_VALUE W_MATCH
- #define W_SECOND 128
-
- #define W_MATCH_FIRST W_MATCH
- #define W_MATCH_SECOND (W_SECOND | W_MATCH)
-
- #define W_INSERT_NODE (W_NODE | W_INSERT)
- #define W_REMOVE_NODE (W_NODE | W_REMOVE)
-
- #define W_INSERT_WATCHER (W_WATCH_CHANGE | W_INSERT)
- /* Not valid during... */
- #define W_REMOVE_WATCHER (W_WATCH_CHANGE | W_REMOVE)
- /* ... INIT[]/DESTROY[] */
-
- The first three flags apply only to non-(list/tree)
- variables. IE: the simple longword type of watched
- variable -- the WatchedValue. W_CHANGE_ZERO is for when
- the variable changes to a zero, W_CHANGE_NON_ZERO is for
- when a variable changes to a non-zero, and W_CHANGE_VALUE
- is for when either happens. Note that the value may have
- already been zero or non-zero. You may use the
- W_WATCH_CHANGE to indicate that you don't want to hear
- about updates to the variables that don't actually CHANGE
- the value that has already been stored [V5].
-
- W_NODE is for any addition or removal of nodes from lists or
- trees. W_WATCH_CHANGE, in conjunction with W_INSERT and
- W_REMOVE, sends notification out when a watcher is added.
- A watcher can get notification when it adds itself, but not
- when it removes itself -- sorry, you'll have to use two
- watchers for that.... W_REMOVE and W_INSERT control
- whether you want notification when something is added or
- removed to/from the list/tree.
-
- W_MATCH is used for a simple matching capability. You can
- watch for a particular object to be removed from the tree,
- or added to the tree, or whatever.... For example, you
- might want to know when a -particular- class was created.
-
- W_MATCH_FIRST uses the value sent to the INIT function as
- the value of, either:
- (a) the value that the WatchedVariable should take on.
- (b)the address of the object added to a list/tree.
- depending on the type of WatchedVariable.
-
- W_MATCH_SECOND uses the value sent to the INIT function
- as the address of a string which would be the name under
- which the node is added to the list/tree.
-
- example:
- You should not have to call this method directly. Instead,
- use the library function call, WatcherDispatch().
-
-
- /*
- * This is roughly the definition of
- * RemoveWatchedTreeStringNode()
- *
- * node is the node to remove
- */
- UseObject(node);
-
- if (ret = RemoveTreeStringNode(&(bt->wv_value), node, name))
- {
- WatcherDispatch(W_REMOVE_NODE,
- (struct WatchedValue *)bt,
- node,
- name);
- }
- DropObject(node);
- return ret;
-
-
- Modified Methods
- METH_DESTROY
- run as:
- function in invoker's process.
-
- arguments:
- none
-
- purpose:
- METH_DESTROY frees an object.
- When DropObject() notices that the usecount has fallen to
- zero, it invokes the METH_DESTROY method on the object.
-
- restrictions:
- You should never invoke this method yourself!
- This method is always invoked by DropObject()!
-
- function:
- Name is Drop()'d from the ATTR_MANAGER node->mnn_name field.
- If W_SECOND was specified during the METH_INIT, the
- node->mnn_value is Drop()'d as well.
- Method is then routed to the superclass.
- If invoked asynchronously, the object pointer is
- transferred out of the msg.
-
- example:
- See example under META_CLASS
-
-
- METH_INIT
- run as:
- function in invoker's process.
-
- arguments:
- JSTR -- the name of the object.
- JOBJ -- object to send the notification method to.
- JSTR -- the notification method.
- long -- various flags controlling the type of watcher
- (object or class), the function of the
- notification, etc.
- long -- optional value for the W_SECOND or W_MATCH_FIRST
- flags. If W_SECOND is specified in the flags
- field, then this method cannot be invoked
- asynchronously, because this would be a pointer
- to a string....
-
- returns the initialized object, or NULL on failure.
-
- purpose:
- Initializes the object and makes it possible to
- ESTABLISH connections with it.
-
- restrictions:
- Sending this method asynchronously may be dangerous,
- depending on what type the last argument to the method is.
- Care must be taken if you want to send this as an
- asynchronous method.
-
- function:
- As with all INIT functions, if the object is not
- successfully INIT'd, the object is UseObject()'d and
- DropObject()'d, resulting in an invocation of the
- METH_DESTROY function. Usually, the party interested in
- receiving notification is UseObject()'d and stored in the
- ATTR_MANAGER's node->mnn_method and node->mnn_object.
- The name is used and put into the structure at
- node->mnn_name. If W_SECOND is specified in the flags
- field, the optional value is treated as a string. In
- addition, this function parcels the long flags value into
- its pieces. The bottom 16 bits become the instrument that
- controls when the Director sends out its notification.
- The next eight bits has only one flag allocated that
- distinguish between SHADOW_OBJECT and SHADOW_CLASS types
- of Directors. (One watches a particular object, the other
- watches all objects in a class.) The last eight bits
- control the working of the internal resource tracking.
- One bit is the SHADOW_AUTOREMOVE. When specified, the
- last connection TERMINATion causes a METH_REMOVE to be sent
- to itself. The other bit is the SHADOW_AUTOBREAK flag.
- When it is specified, the REMOVE method automatically
- TERMINATEs all connections. Unless you do something very
- bizarre, you should specify both bits. An internal bit
- (SHADOW_REMOVED) prevents an infinite recursion when both
- bits are specified.
-
- You can control the notification so that it occurs only on
- specific types of events. This is controlled by the first
- 16 bits of the 'flags' parameter. The W_* flags which
- control the notification restriction are specified in the
- method immediately above this one.
-
- Method then is routed to the superclass.
-
- example:
- see the METH_DIRECTOR_ESTABLISH method example for this
- class above.
-
-
- METH_REMOVE
- run as:
- function in invoker's process.
-
- arguments:
- none
-
- purpose:
- Removes the object from the system and makes it impossible
- to ESTABLISH further connections.
- May also disengage any current connections if
- SHADOW_AUTOBREAK was specified during the METH_INIT.
-
- restrictions:
- none
-
- function:
- If the Director had its SHADOW_AUTOBREAK specified, all
- connections are TERMINATEd. The notification destination
- object and method are Drop()'d, cleared.
- Method is then routed to the superclass.
-
- example:
- see the METH_DIRECTOR_ESTABLISH method example for this
- class above.
-
-
-
- Class: PATCHER_CLASS
- Superclass: ROOT_CLASS
- Include File: <shadow/method.h>
-
- The class that creates patches on pre-existing methods.
-
- Attributes:
- ATTR_METHODHANDLER -- struct MethodHandler followed by a class
- pointer which indicates the class that was
- patched. [Attribute is located at address
- offset of eight from the object, this
- behaviour is depended on by the OS.]
-
- Modified Methods:
- METH_DESTROY
- run as:
- function in invoker's prcoess.
-
- arguments:
- none
-
- purpose:
- METH_DESTROY frees an object.
- When DropObject() notices that the usecount has fallen to
- zero, it invokes the METH_DESTROY method on the object.
-
- restrictions:
- You should never invoke this method yourself!
- This method is always invoked by DropObject()!
-
- function:
- Drop()s the procObject, defnObject and MethodID of the
- patch. Invokes the superclass, then transfers the object
- from the msg so that it will work properly when/if invoked
- asynchronously.
-
- example:
- See example under META_CLASS
-
-
- METH_INIT
- run as:
- function in invoker's process.
-
- arguments:
- APTR -- A MethodTag. This does NOT cause problems for
- ASYNC methods....
- JOBJ -- class to patch, or an object of that class; in
- which case, unless the object has an
- ATTR_PATCHEDVERBS attribute, the class of the
- passed object, not the passed object, is patched.
-
- returns the initialized object, or NULL on failure.
-
- purpose:
- Initializes the object and installs the patch.
-
- restrictions:
- You should be prepared to handle the patched method before
- invoking this method.
-
- function:
- Usually, the method to be patched is found (failure to
- find the method in the class requested causes the patch
- to fail -- DOES NOT CHECK superclasses!), procObject and
- defnObject in the MethodTag fields are Use()'d and put
- into the ATTR_METHODHANDLER. MethodID is also Use()'d.
- In addition, all other MethodTag information is copied into
- the MethodHandler structure. Class information is saved in
- the patched-class field -- this is NOT Use()'d! Patch is
- inserted.
- Method is then routed to the superclass.
-
- example:
- /*
- * The patch data (usually a global)
- *
- * This method returns stuff in both d0 and d1, hence its
- * prototype as 'double'. If D1 is non-zero, the patches
- * with lower priority (this includes the method itself)
- * are called. If D1 is zero, the method invocation
- * process is terminated.
- */
- extern double PreTestMethod(METHOD_ARGS);
-
- METHOD_TAG preMethod =
- {
- "Method TEST",
- NULL, NULL,
- INVOKE_SYNC,
- METH_FLAG_CHECK_CONTINUE |
- METH_FLAG_CLASS,
- 1, /* The priority */
- (METHODFUNCTYPE)PreTestMethod, NULL
- };
- /*
- * Add a method patch.
- * Note we CANNOT use SetupMethodTags!
- */
- preMethod.mtag_procObject = dosTaskClass;
- preMethod.mtag_defnObject = CurrentProcess();
-
- prePatch = CreateInstance(NULL, PATCHER_CLASS,
- META_CLASS,
- &preMethod,
- my_dos_class, /*
- * Actual
- * instance
- * of
- * class.
- */
- METHOD_END);
- .
- .
- .
- /*
- * Cleanup
- */
- RemoveObject(prePatch);
-
-
- METH_REMOVE
- run as:
- function in invoker's process.
-
- arguments:
- none
-
- purpose:
- Removes the object and the patch from the system.
-
- restrictions:
- none
-
- function:
- Patch is removed from the ATTR_PATCHEDVERBS list of the
- class that this object is patching.
- Method is then routed to the superclass.
-
- example:
- see the METH_INIT method example for this class above.
-
-
- Class: PROCESS_CLASS
- Superclass: ROOT_CLASS
- Include File: <shadow/process.h>
-
- The class that creates processes.
-
- Attributes:
- ATTR_JAZZPROCESS -- struct JazzProcess. Again, the system expects
- to find this attribute at offset 8. Do not
- hack around and move it, please.
- ATTR_RESOURCETREE -- Watched binary tree that you can store
- your resources on.
- ATTR_RESOURCESTACK -- Watched list that you can store last
- minute removal resources. Freed only
- during The DISASSOCIATE method.
- New Methods:
- METH_PROC_ASSOCIATE
- run as:
- function in invoker's process.
-
- purpose:
- Completes the initialization of the object and allocates
- the process' ports. Certain things need to be allocated
- inside of a process' context (like signals, ports, etc.),
- so this method exists to allow you to do our allocation
- at this time.
-
- restrictions:
- This method should only be invoked in the context of a
- currently running process. The METH_INIT handles
- this correctly for new processes, InitOOProgram()
- handles a default version for the programs you start
- up.
- If compiling with the small data model, you must call
- either the equivalent of geta4() or prototype your
- method-function with the __saveds keyword.
-
- arguments:
- JSTR -- name of the current process. Defaults to
- FindTask(NULL)->tc_node.ln_Name
- TASK -- pointer to the task. Defaults to
- FindTask(NULL). Needs to be run in the
- that task's frame anyway, because Signals
- for message ports are allocated....
-
- returns object which should NOT be DROP()'d! This is
- safe because the method can only be invoked in that
- process to begin with....
-
- function:
- Creates a SHADOW process object for a process that already
- exists. Stores the object into task->tc_UserData.
- Creates ports and synchronous messages for this
- process.
- Sends the METH_INIT method to the class' superclass -- the
- ROOT_CLASS.
-
- example:
- /*
- * This is roughly the source to InitOOProgram()
- */
-
- procClass = FindShadowClass(PROCESS_CLASS);
- myProc = DoShadow(procClass,
- NULL,
- METH_CREATE,
- METHOD_END);
- myProc = DoShadow(myProc,
- NULL,
- METH_PROC_ASSOCIATE,
- name,
- METHOD_END);
- DropObject(procClass);
-
- .
- .
- .
-
- /*
- * Don't forget to call the RemoveCurrentProgram()
- * function or some equivalent during cleanup!
- */
-
-
- METH_PROC_DISASSOCIATE
- run as:
- function in process associated with the object that
- the method is being invoked on.
-
- arguments:
- none
-
- purpose:
- Completes the process end of the process destruction.
- Certain items under AmigaDOS must be freed in the
- process that allocated them -- like ports and signals.
- This method allows you someplace to put such items.
-
- restrictions:
- This is a system invoked method similar to METH_DESTROY.
- You may subclass this method, but do not call it.
- Again, be careful about the small data model (see above
- method).
-
- function:
- Shuts various system ports, handles remaining messages,
- leaves the ports, deletes the synchronous message.
- Removes all the resources (RemoveResources(object, TRUE)).
- Deletes the process name.
- When the method returns, the system will call the
- METH_DESTROY on the process object's superclass to complete
- the object destruction. The process will then return to
- AmigaDOS.
- example:
- You should never call this function.
- Process cleanup is automatic when a -created- program
- exits. When an Amiga-launched app ends, the programmer
- should call RemoveCurrentProgram().
-
-
- METH_PROC_HANDLER
- run as:
- function in process associated with the object that
- the method is being invoked on.
-
- arguments:
- none
-
- purpose:
- Handles all incoming SHADOW messages. You can subclass
- this and override this behaviour to include intercepting
- Intuition events as well....
-
- restrictions:
- This method should only be invoked in the context of a
- currently running process. The METH_INIT handles
- this correctly for new processes, no handling is done
- for your own program -- you decide where to finally
- wait for all the mehods....
-
- If compiling with the small data model, you must call
- either the equivalent of geta4() or prototype your
- method-function with the __saveds keyword.
-
- function:
- Processes all SHADOW messages.
- Leaves when ^C is detected.
-
- example:
- From <shadow/shadow_proto.h>
- DoShadow(CurrentProcess(), NULL, METH_PROC_HANDLER,
- METHOD_END);
- The METH_PROC_HANDLER is automatically called for
- SHADOW-launched prcesses.
-
-
- Modified Methods:
- METH_DESTROY
- run as:
- function in invoker's process.
-
- arguments:
- none
-
- purpose:
- METH_DESTROY frees an object.
- When DropObject() notices that the usecount has fallen to
- zero, it invokes the METH_DESTROY method on the object.
-
- restrictions:
- You should never invoke this method yourself!
- This method is always invoked by DropObject()!
- This method MUST ALWAYS BE INVOKE_CALL! Never
- subclass this method to be INVOKE_SYNC or INVOKE_MSG_SYNC.
-
- function:
- ATTR_RESOURCETREE is freed.
-
- The SHADOW_PROC_FLAGS_DESTROYED bit is set to inform the
- process that it should really go away. A ^C is sent
- to the associated process to tell it to go away.
- Upon receipt of these signals, the METH_PROC_HANDLER
- should return. The system will then call the
- METH_PROC_DISASSOCIATE and then the METH_DESTROY on the
- superclass of process class, the root class.
-
- If there is no associated process (ie: if the METH_INIT
- didn't work properly), the superclass is called directly.
-
- example:
- See example under META_CLASS
-
-
- METH_INIT
- run as:
- function in invoker's process.
- arguments:
- JSTR -- name of the process to create.
- JOBJ -- The parent object. if no parent object, the
- calling process is used as the parent.
- SEMF -- an optional semaphore to own shared by the started
- process. Semaphore is Release()'d when task exits.
- TAGL -- a NULL terminated array of struct TagItem to send to
- the CreateNewProc invok. If the INIT fails AFTER
- the process is created, the tags' ti_Tag are set
- to TAG_IGNORE, so you don't have to free the
- resources that might be in the TAGL if the process
- fails to be created. (In fact, the ti_Tags are
- set to TAG_IGNORE even if the process successfully
- opens.)
- APTR -- Pointer to an optional ProcessInitFrame. This is
- used as an override array to the ASSOCIATE method
- to allow the METH_INIT to initialize other classes
- of processes in an arbitrarily coplex manner.
- APTR -- Pointer to an optional ProcessHandlerFrame. This is
- used as an override array to the HANDLER method
- to allow METH_INIT to initialize other classes of
- processes in an arbitrarily complex manner.
-
- returns the initialized object, or NULL on failure.
-
- purpose:
- Create a new process and get the process up and running.
-
- restrictions:
- If the last two fields are used, this function should
- not be called asynchronously. The Init and Handler Frames
- may grow arbitrarily large in size to account for
- HANDLER or ASSOCIATE methods that require a large number
- of arguments.
- If you pass resources in the tags (like file handles), this
- function should, again, not be called asynchronously.
-
- function:
- Using the two optional frames (and the local default
- frames), the ASSOCIATE and HANDLER methods are preparsed
- and sent to the newly created process in the form of
- messages (allowing asynchronous, safe startups).
-
- The superclass is NOT called, that's done inside of
- the PROC_ASSOCIATE method.
-
- Semaphore Obtain()'d shared, process is created, and various
- magic done to ensure a safe startup between processes.
-
- Will set all ti_Tag elements to TAG_IGNORE if process is
- successfully started, even if process subsequently shuts
- down due to a startup error. This allows you to free
- resources correctly (hopefully) when process' fail to start
- properly, independent upon whether it was the
- CreateNewProc() invocation that failed, or something else....
-
- example:
- /*
- * This example demonstrates how to get
- * the INIT method to invoke a subclassed
- * METH_PROC_HANDLER with arguments different from the
- * default. In this case, the METH_PROC_HANDLER is
- * responsible for defining a new class, so the class
- * creation arguments are sent into the METH_PROC_HANDLER.
- *
- * Also note, this is code from the METH_INIT of this
- * process-class, so the METH_INIT is actually sent
- * on to the superclass.
- */
- struct MyHandlerFrame {
- struct ProcessHandlerFrame mf_handlerArgs;
- char *mf_newName;
- struct MethodTag *mf_methods;
- struct AttributeTag *mf_attrs;
- void *END;
- } mhf;
-
- mhf.mf_handlerArgs.phf_methodID = NULL; /* default! */
- /*
- * New arguments for the subclassed METH_PROC_HANDLER!
- */
- mhf.mf_handlerArgs.phf_args[0] = paramClassName;
- mhf.mf_newName = newName;
- mhf.mf_methods = methods;
- mhf.mf_attrs = attrs;
- mhf.END = METHOD_END;
-
- process = DoShadow(object, class->meta_superClass,
- MethodID,
- processName,
- NULL, NULL, NULL,
- NULL,
- &mhf,
- METHOD_END);
-
- return process;
-
- .
- .
- .
-
- /*
- * Cleanup!
- */
- RemoveObject(process);
-
-
- METH_REMOVE
- run as:
- function in process associated with the object that
- the method is being invoked on.
-
- arguments:
- none
-
- purpose:
- Removes the process object from the system.
-
- restrictions:
- none
-
- function:
- Sets the Remove flag.
- Method is then routed to the superclass.
- A call to RemoveResources(object, FALSE) is made.
-
- example:
- see the METH_INIT method example for this class above.
-